﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Resources;
using System.IO;
using System.Windows.Markup;

namespace ThemeLoader
{
    public class ThemeLoader : IThemeLoader
    {
        public void DownloadAsyncZippedStream(string themeZipFilePath, Action<OpenReadCompletedEventArgs> loadFinishedHandler)
        {
            // download a target compressed theme file
            WebClient webclient = new WebClient();

            OpenReadCompletedEventHandler handler = null;

            handler = (s,e) =>
                {
                    webclient.OpenReadCompleted -= handler;
                    loadFinishedHandler(e);           
                };

            webclient.OpenReadCompleted += handler;
            webclient.OpenReadAsync(new Uri(Application.Current.Host.Source, themeZipFilePath));
        }

        public void DownloadTheme(string themeZipFilePath, string themeContentFileName, Action<ThemeDownloadedEventArgs> loadFinishedHandler)
        {
            this.DownloadAsyncZippedStream(themeZipFilePath, downloadArgs =>
                {
                    ThemeDownloadedEventArgs args;

                    if (downloadArgs.Error != null || downloadArgs.Cancelled)
                    {
                        args = new ThemeDownloadedEventArgs(downloadArgs.Error, downloadArgs.Cancelled, downloadArgs.UserState, null);
                    }
                    else 
                    {
                        try
                        {
                            var theme = this.GetThemeFromZipStream(downloadArgs.Result, themeContentFileName);
                            args = new ThemeDownloadedEventArgs(null, false, downloadArgs.UserState, theme);
                        }
                        catch (Exception e)
                        {
                            args = new ThemeDownloadedEventArgs(e, false, downloadArgs.UserState, null);
                        }
                    }

                    loadFinishedHandler(args);
                });
        }

        public ResourceDictionary GetThemeFromZipStream(Stream zipStream, string themeContentFileName)
        {
            if (zipStream == null)
            {
                throw new ArgumentNullException("zipStream");
            }

            if (themeContentFileName == null)
            {
                throw new ArgumentNullException("themeContentFileName");
            }

            try
            {
                // retrieve XAML file from the zip package
                StreamResourceInfo zipInfo = new StreamResourceInfo(zipStream, "application/zip");
                StreamResourceInfo themeInfo = Application.GetResourceStream(zipInfo, new Uri(themeContentFileName, UriKind.Relative));

                // read and load the XAML file as a ResourceDictionary
                string themeXaml = new StreamReader(themeInfo.Stream).ReadToEnd();
                ResourceDictionary theme = XamlReader.Load(themeXaml) as ResourceDictionary;

                return theme;
            }
            catch (Exception e)
            {
                throw new ThemeLoadException("Error occured during loading ResourceDictionary from streamn, check inner exception for details", e);                                    
            }      
        }
    }
}
